/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
* ComGLHoodIView.java
*
* Created on November 15, 2007, 4:36 PM
 */
package gui.genomemap.view.inputView;

import genomemap.worker.AnnealMachine;
import genomemap.worker.Annealable;

import gui.genomemap.event.event.WorkerInputEvent;
import gui.genomemap.inputModel.AnnealIModel;
import gui.genomemap.inputModel.ProgCurveIModel;
import gui.genomemap.popup.UsedOrderPopup;
import gui.genomemap.view.inputView.options.ProgCurveIOptions;

import javautil.collections.ArrayUtil;
import javautil.swing.SwingUtil;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.JPopupMenu;
import javax.swing.JTable;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;

/**
 *
 * @author  stewari1
 */
public class ProgCurveIView extends InputView {

    /** Field description */
    private final ProgCurveIOptions optionsDialog = new ProgCurveIOptions(new javax.swing.JFrame(),
                                                        false);

    /** Field description */
    private JPopupMenu tablePopUp = null;


    // Variables declaration - do not modify//GEN-BEGIN:variables

    /** Field description */
    private javax.swing.JLabel annealMachineType;

    /** Field description */
    private javax.swing.JComboBox annealMachineType_JComboBox;

    /** Field description */
    private javax.swing.JCheckBox embedSeq_JCheckBox;

    /** Field description */
    private javax.swing.JLabel jLabel1;

    /** Field description */
    private javax.swing.JLabel jLabel2;

    /** Field description */
    private javax.swing.JLabel jLabel3;

    /** Field description */
    private javax.swing.JLabel jLabel4;

    /** Field description */
    private javax.swing.JComboBox lHoodType_JComboBox;

    /** Field description */
    private javax.swing.JLabel linkageGrp_JLabel;

    /** Field description */
    private javax.swing.JComboBox linkagegrp_JComboBox;

    /** Field description */
    private javax.swing.JButton options_JButton;

    /** Field description */
    private javax.swing.JTextField order_JTextField;

    /** Field description */
    private javax.swing.JButton run_JButton;

    /** Field description */
    private javax.swing.JTextField segCount_JTextField;

    /** Field description */
    private javax.swing.JComboBox segProbeCount_JComboBox;

    /** Field description */
    private javax.swing.JCheckBox usedOrder_JCheckBox;

    /** Creates new form ComGLHoodIView */
    public ProgCurveIView() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */


    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        run_JButton                 = new javax.swing.JButton();
        options_JButton             = new javax.swing.JButton();
        linkageGrp_JLabel           = new javax.swing.JLabel();
        linkagegrp_JComboBox        = new javax.swing.JComboBox();
        jLabel1                     = new javax.swing.JLabel();
        order_JTextField            = new javax.swing.JTextField();
        usedOrder_JCheckBox         = new javax.swing.JCheckBox();
        jLabel2                     = new javax.swing.JLabel();
        lHoodType_JComboBox         = new javax.swing.JComboBox();
        embedSeq_JCheckBox          = new javax.swing.JCheckBox();
        jLabel3                     = new javax.swing.JLabel();
        jLabel4                     = new javax.swing.JLabel();
        segCount_JTextField         = new javax.swing.JTextField();
        segProbeCount_JComboBox     = new javax.swing.JComboBox();
        annealMachineType           = new javax.swing.JLabel();
        annealMachineType_JComboBox = new javax.swing.JComboBox();

        run_JButton.setText("Run");
        run_JButton.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                run_JButtonActionPerformed(evt);
            }

        });
        options_JButton.setText("Options");
        options_JButton.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                options_JButtonActionPerformed(evt);
            }

        });
        linkageGrp_JLabel.setText("Linkage Group");
        linkagegrp_JComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {
            "1", "2", "3", "4", "5", "6", "7"
        }));
        jLabel1.setText("Enter Starting Order");
        order_JTextField.setToolTipText("Enter \",\" seperated natural numbers");
        usedOrder_JCheckBox.setText("Choose Used Orders ?");
        usedOrder_JCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
        usedOrder_JCheckBox.setMargin(new java.awt.Insets(0, 0, 0, 0));
        usedOrder_JCheckBox.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent evt) {
                usedOrder_JCheckBoxActionPerformed(evt);
            }

        });
        jLabel2.setText("Anneal Criterion");
        lHoodType_JComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {
            "Physical Likelihood",
            "Joint Likelihood", "Hamming Distance" }));
        embedSeq_JCheckBox.setText("Embed Sequence");
        embedSeq_JCheckBox.setBorder(javax.swing.BorderFactory.createEmptyBorder(1, 1, 1, 1));
        jLabel3.setText("Segment Probe Count");
        jLabel4.setText("Total # of Segments");
        segProbeCount_JComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "10",
                "20", "30", "40" }));
        annealMachineType.setText("Anneal Machine Type");
        annealMachineType_JComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] {
            "Simulated Annealing",
            "Random Cost" }));

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);

        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup().addGap(32, 32, 32).addGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                        layout.createSequentialGroup().addGroup(
                            layout.createParallelGroup(
                                javax.swing.GroupLayout.Alignment.LEADING).addComponent(
                                jLabel4).addComponent(linkageGrp_JLabel).addComponent(
                                jLabel1).addComponent(annealMachineType).addComponent(
                                jLabel3)).addPreferredGap(
                                    javax.swing.LayoutStyle.ComponentPlacement.RELATED).addGroup(
                                    layout.createParallelGroup(
                                        javax.swing.GroupLayout.Alignment.LEADING).addComponent(
                                        order_JTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 160, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(
                                        linkagegrp_JComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(
                                        segCount_JTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 50, javax.swing.GroupLayout.PREFERRED_SIZE).addGroup(
                                        layout.createParallelGroup(
                                            javax.swing.GroupLayout.Alignment.TRAILING, false).addComponent(
                                                segProbeCount_JComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(
                                                    annealMachineType_JComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(
                                                        lHoodType_JComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 130, Short.MAX_VALUE))).addGap(
                                                            84, 84, 84).addGroup(
                                                                layout.createParallelGroup(
                                                                    javax.swing.GroupLayout.Alignment.LEADING).addComponent(
                                                                        embedSeq_JCheckBox).addGroup(
                                                                            layout.createSequentialGroup().addComponent(
                                                                                options_JButton).addPreferredGap(
                                                                                    javax.swing.LayoutStyle.ComponentPlacement.RELATED).addComponent(
                                                                                        run_JButton)).addComponent(
                                                                                            usedOrder_JCheckBox)).addGap(
                                                                                                0, 0, Short.MAX_VALUE)).addComponent(
                                                                                                    jLabel2)).addContainerGap()));
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                layout.createSequentialGroup().addContainerGap().addGroup(
                    layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGroup(
                        layout.createParallelGroup(
                            javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
                            linkagegrp_JComboBox, javax.swing.GroupLayout.PREFERRED_SIZE,
                            javax.swing.GroupLayout.DEFAULT_SIZE,
                            javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(
                                linkageGrp_JLabel)).addGroup(
                                    layout.createParallelGroup(
                                        javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
                                        options_JButton).addComponent(run_JButton))).addGap(
                                            13, 13, 13).addGroup(
                                                layout.createParallelGroup(
                                                    javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
                                                        jLabel1).addComponent(
                                                            order_JTextField,
                                                                javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                    javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                        javax.swing.GroupLayout.PREFERRED_SIZE).addComponent(
                                                                            usedOrder_JCheckBox)).addPreferredGap(
                                                                                javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addGroup(
                                                                                    layout.createParallelGroup(
                                                                                        javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
                                                                                            jLabel2).addComponent(
                                                                                                embedSeq_JCheckBox).addComponent(
                                                                                                    lHoodType_JComboBox,
                                                                                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                            javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                javax.swing.GroupLayout.PREFERRED_SIZE)).addGap(
                                                                                                                    13,
                                                                                                                    13,
                                                                                                                    13).addGroup(
                                                                                                                        layout.createParallelGroup(
                                                                                                                            javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
                                                                                                                                annealMachineType).addComponent(
                                                                                                                                    annealMachineType_JComboBox,
                                                                                                                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                                                            javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                                                javax.swing.GroupLayout.PREFERRED_SIZE)).addGap(
                                                                                                                                                    12,
                                                                                                                                                    12,
                                                                                                                                                    12).addGroup(
                                                                                                                                                        layout.createParallelGroup(
                                                                                                                                                            javax.swing.GroupLayout.Alignment.BASELINE).addComponent(
                                                                                                                                                                jLabel3).addComponent(
                                                                                                                                                                    segProbeCount_JComboBox,
                                                                                                                                                                        javax.swing.GroupLayout.PREFERRED_SIZE,
                                                                                                                                                                            javax.swing.GroupLayout.DEFAULT_SIZE,
                                                                                                                                                                                javax.swing.GroupLayout.PREFERRED_SIZE)).addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED).addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE).addComponent(jLabel4).addComponent(segCount_JTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)).addContainerGap(25, Short.MAX_VALUE)));
        layout.linkSize(javax.swing.SwingConstants.VERTICAL, annealMachineType_JComboBox,
                        lHoodType_JComboBox, linkagegrp_JComboBox, order_JTextField,
                        segCount_JTextField, segProbeCount_JComboBox);

    }    // </editor-fold>//GEN-END:initComponents

    /**
     * Method description
     *
     * @param evt description
     */
    private void usedOrder_JCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {    // GEN-FIRST:event_usedOrder_JCheckBoxActionPerformed

        if (!usedOrder_JCheckBox.isSelected()) {

            System.out.println("selected not");

            if (tablePopUp != null) {
                tablePopUp.setVisible(false);
            }

        } else {

            System.out.println("selected");

            if (tablePopUp == null) {

                tablePopUp = UsedOrderPopup.createPopup(getView());


                // add popup menu listener
                tablePopUp.addPopupMenuListener(new PopupMenuListener() {

                    public void popupMenuCanceled(PopupMenuEvent e) {}
                    public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
                        usedOrder_JCheckBox.setSelected(false);
                    }
                    public void popupMenuWillBecomeVisible(PopupMenuEvent e) {}

                });


                // add cell double click listener to the table under the popup first time
                final JTable table = (JTable) tablePopUp.getClientProperty(UsedOrderPopup.TABLE);

                table.addMouseListener(new MouseAdapter() {

                    public void mousePressed(MouseEvent e) {

                        int x = e.getX();
                        int y = e.getY();

                        if (e.getClickCount() == 2) {

                            int col = table.getSelectedColumn();

                            if (col != 2) {
                                return;
                            }

                            int row = table.getSelectedRow();

                            ProgCurveIView.this.setOrderString("" + table.getValueAt(row, col));
                        }
                    }

                });
            }

            tablePopUp.show(this, 100, 90);
        }

    }    // GEN-LAST:event_usedOrder_JCheckBoxActionPerformed

    String getOrderString() {
        return order_JTextField.getText();
    }

    public void setOrderString(String orderString) {
        order_JTextField.setText(orderString);
    }

    /**
     * Method description
     *
     * @param evt description
     */
    private void options_JButtonActionPerformed(java.awt.event.ActionEvent evt) {    // GEN-FIRST:event_options_JButtonActionPerformed

        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {

                optionsDialog.setLocationRelativeTo(null);
                optionsDialog.setVisible(true);
            }

        });

    }    // GEN-LAST:event_options_JButtonActionPerformed

    @Override
    public void referesh() {

        if (getInputModel() == null) {

            setEnabledRunModel(true);
            linkagegrp_JComboBox.setSelectedItem("1");
            setOrderString("");

            return;
        }

        ProgCurveIModel progCurveIModel = (ProgCurveIModel) getInputModel();

        setOrder(progCurveIModel.getOrderSet());
        linkagegrp_JComboBox.setSelectedItem("" + progCurveIModel.getLinkageGroup());
        segProbeCount_JComboBox.setSelectedItem(progCurveIModel.getSegProbeCount());
        optionsDialog.setOptions(progCurveIModel);
    }

    /**
     * Method description
     *
     * @param evt description
     */
    private void run_JButtonActionPerformed(java.awt.event.ActionEvent evt) {    // GEN-FIRST:event_run_JButtonActionPerformed

        ProgCurveIModel inputModel = new ProgCurveIModel();


        // set linkage group
        inputModel.setLinkageGroup(
            Integer.parseInt((String) linkagegrp_JComboBox.getSelectedItem()));


        // set segProbeCount
        inputModel.setSegProbeCount(
            Integer.parseInt(segProbeCount_JComboBox.getSelectedItem().toString()));


        // set order
        String orderString = getOrderString();

        if (orderString.length() == 0) {

            SwingUtil.showErrorDialog(this, "The order text field is empty !");

            return;
        }

        String[] orders = orderString.split(",");

        if (orders.length < inputModel.getSegProbeCount()) {

            SwingUtil.showErrorDialog(
                this, "The probe order must be at least the size of segment probe count !");

            return;
        }

        for (String val : orders) {

            inputModel.addOrder(Integer.parseInt(val));
        }


        // the integer division is deliberate
        inputModel.setSegmentCount(orders.length / inputModel.getSegProbeCount());


        // set the anneal machine type
        int index = annealMachineType_JComboBox.getSelectedIndex();

        if (index == 0) {
            inputModel.setAnnealMachineType(AnnealMachine.MACHINE_TYPE_SIMULATED_ANNEALING);
        }

        if (index == 1) {
            inputModel.setAnnealMachineType(AnnealMachine.MACHINE_TYPE_RANDOM_COST);
        }


        // set the anneal criterion
        index = lHoodType_JComboBox.getSelectedIndex();

        if (index == 0) {
            inputModel.setAnnealCriterion(Annealable.ANNEAL_CRITERION_PHOOD);
        }

        if (index == 1) {
            inputModel.setAnnealCriterion(Annealable.ANNEAL_CRITERION_JHOOD);
        }

        if (index == 2) {
            inputModel.setAnnealCriterion(Annealable.ANNEAL_CRITERION_HAM_DIST);
        }


        // get other options  for ProgCurve from the options dialog
        optionsDialog.getOptions(inputModel);


        // set the annealIModelSet by adding
        // get the anneal options
        AnnealIModel annealIModel = inputModel.getAnnealInputOptions();

        annealIModel.setLinkageGroup(inputModel.getLinkageGroup());

        Integer[] entireProbeOrder = ArrayUtil.getIntegerArray(inputModel.getOrder());
        int segmentLen             = inputModel.getSegProbeCount();
        int segments               = inputModel.getSegmentCount();

        try {

            for (int segment = 1; segment <= segments - 1; segment++) {

                int endPos                       = segment * segmentLen;
                int[] segmentOrder =
                    ArrayUtil.getIntegerArray(ArrayUtil.getSubArray(entireProbeOrder,
                        Integer.class, 1, endPos));
                AnnealIModel segmentAnnealIModel = (AnnealIModel) annealIModel.clone();

                segmentAnnealIModel.setOrder(segmentOrder);
                inputModel.addAnnealIModel(segmentAnnealIModel);
            }


            // the last segment
            int endPos                       = entireProbeOrder.length;
            int[] segmentOrder = ArrayUtil.getIntegerArray(ArrayUtil.getSubArray(entireProbeOrder,
                                     Integer.class, 1, endPos));
            AnnealIModel segmentAnnealIModel = (AnnealIModel) annealIModel.clone();

            segmentAnnealIModel.setOrder(segmentOrder);
            inputModel.addAnnealIModel(segmentAnnealIModel);

        } catch (CloneNotSupportedException ex) {
            Logger.getLogger(ProgCurveIView.class.getName()).log(Level.SEVERE, null, ex);
        }

        WorkerInputEvent workerInputEvent = new WorkerInputEvent(this, WorkerInputEvent.PROG_CURVE);

        workerInputEvent.setInputModel(inputModel);
        fireWorkerInputEvent(workerInputEvent);

    }    // GEN-LAST:event_run_JButtonActionPerformed

    @Override
    public void setEnabledRunModel(boolean enabled) {
        run_JButton.setEnabled(enabled);
    }


    // End of variables declaration//GEN-END:variables
}
